package com.wx.house.common.exception;

import com.wx.house.core.pojo.base.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.LinkedHashMap;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.wx.house.common.exception.ExceptionType.*;


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public Result handleException(Exception e, HttpServletRequest request) {
	log.error("url:{},msg:{}", request.getRequestURI(), e.getMessage());
	e.printStackTrace();
	//TODO 记录系统异常
	return Result.error(EXCEPTION, e.getMessage(), "系统异常");
}

@ExceptionHandler(value = BusinessException.class)
public Result handleBusinessException(BusinessException e, HttpServletRequest request) {
	log.error("url{},msg{}", e.getMessage(), "业务异常:" + request.getRequestURI());
	e.printStackTrace();
	//TODO 记录业务异常
	return Result.error(BUSINESS_EXCEPTION, null, e.getMessage());
}

@ExceptionHandler(value = ServerException.class)
public Result handleServerException(ServerException e, HttpServletRequest request) {
	log.error("url{},msg{}", request.getRequestURI(), e.getMessage());
	e.printStackTrace();
	//TODO 记录服务器组件异常
	return Result.error(SERVER_EXCEPTION, e.getMessage(), "服务运行异常");
}

@ExceptionHandler(value = UserException.class)
public Result handleServer(UserException e, HttpServletRequest request) {
	log.error("url{},msg{}", request.getRequestURI(), e.getMessage());
	e.printStackTrace();
	//TODO 记录服务器组件异常
	return Result.error(e.getCode(), null, e.getMessage());
}

@ExceptionHandler(MaxUploadSizeExceededException.class)
public Result handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e, HttpServletRequest request) {
	log.error("url{},msg{}", request.getRequestURI(), e.getMessage());
	e.printStackTrace();
	return Result.error(MAX_UPLOAD_SIZE_EXCEPTION, "文件大小超过传输限制", "其他异常");
}

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, HttpServletRequest request) {
	BindingResult bindingResult = ex.getBindingResult();
	LinkedHashMap<String, String> result = IntStream
			                                       .range(0, bindingResult.getFieldErrorCount())
			                                       .mapToObj(i -> bindingResult.getFieldErrors()
					                                                      .get(i))
			                                       .collect(Collectors.toMap(
					                                       FieldError::getField,
					                                       FieldError::toString,
					                                       (k, v) -> v,
					                                       LinkedHashMap::new));
	
	return Result.error(PARAM_ERROR_EXCEPTION, result, "参数异常");
}


@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
public Result handleConstraintViolationException(ConstraintViolationException ex, HttpServletRequest request) {
	LinkedHashMap<String, String> result = ex.getConstraintViolations()
			                                       .stream()
			                                       .collect(Collectors.toMap(e -> e.getPropertyPath().toString().split("\\.")[1],
					                                       ConstraintViolation::getMessage,
					                                       (a, b) -> b,
					                                       LinkedHashMap::new));
	return Result.error(PARAM_ERROR_EXCEPTION, result, "参数异常");
}

@ExceptionHandler({BindException.class})
@ResponseBody
public Result handleBeanPropertyBindingResult(BindException ex) {
	BindingResult bindingResult = ex.getBindingResult();
	LinkedHashMap<String, String> result = IntStream
			                                       .range(0, bindingResult.getFieldErrorCount())
			                                       .mapToObj(i -> bindingResult.getFieldErrors()
					                                                      .get(i))
			                                       .collect(Collectors.toMap(FieldError::getField,
					                                       e -> Objects.requireNonNull(e.getDefaultMessage()).split(":")[1],
					                                       (a, b) -> b,
					                                       LinkedHashMap::new));
	return Result.error(PARAM_ERROR_EXCEPTION, result, "参数异常");
}

@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public Result handleJsonParseException(HttpMessageNotReadableException e) {
	e.printStackTrace();
	return Result.error(JSON_ERROR_EXCEPTION, null, "json解析失败");
}

}
